package main

import (
	"errors"
	"fmt"
	"math/rand"
)

// 数组模拟队列
// 队列是一个有序列表，可以用数组或链表实现
// 遵循先入先出的原则 FIFO
func main() {
	simulateUnidirectionalQueue()
}

// simulateUnidirectionalQueue
//
//	@Description: 模拟单向队列：
//
// ------------队列信息start------------
// Front=9 Tail=9
// |  0  ||  1  ||  2  ||  3  ||  4  ||  5  ||  6  ||  7  ||  8  ||  9  |
// |  0  ||  0  ||  0  ||  0  ||  0  ||  0  ||  0  ||  0  ||  0  ||  0  |
// ------------队列信息end------------
func simulateUnidirectionalQueue() {
	q := &Queue{
		MaxSize: 10,
		Front:   -1,
		Rear:    -1,
		Array:   [10]int{},
	}
	var key int
	for {
		fmt.Println("1. 添加数据到队列	2. 获取数据	3. 显示队列")
		fmt.Scanln(&key)
		switch key {
		case 1:
			var v = rand.Intn(9) + 1
			err := q.addQueue(v)
			if err != nil {
				fmt.Printf("添加元素:%v ERROR=%v \n", v, err)
			} else {
				fmt.Printf("添加元素成功:%v\n", v)
			}
			q.showQueue()
		case 2:
			value, err := q.getQueue()
			if err != nil {
				fmt.Printf("获取元素失败 ERROR=%v \n", err)
			} else {
				fmt.Printf("获取元素成功:%v\n", value)
			}
			q.showQueue()
		case 3:
			q.showQueue()
		default:
			fmt.Println("输入错误，请重新输入！")
		}
	}

}

type Queue struct {
	MaxSize int     // 队列最大容量
	Array   [10]int // 存放数据
	Front   int     // 指向队列头
	Rear    int     // 指向队列尾
}

// addQueue
//
//	@Description:
//	@receiver q
//	@param value
//	@return err
func (q *Queue) addQueue(value int) (err error) {
	//判断队列是否已满
	if q.Rear == q.MaxSize-1 {
		return errors.New("队列已满")
	}
	q.Rear++                // 队尾指针后移
	q.Array[q.Rear] = value // 赋值
	return nil
}

// getQueue
//
//	@Description: 获取
//	@receiver q
//	@return value
//	@return err
func (q *Queue) getQueue() (value int, err error) {
	//判断队列是否为空
	if q.Front == q.Rear {
		return 0, errors.New("队列为空")
	}
	q.Front++             // 队头指针后移
	v := q.Array[q.Front] //获取队头元素
	q.Array[q.Front] = 0  // 赋值0
	return v, nil
}

// showQueue
//
//	@Description: 打印队列信息
//	@receiver q
func (q *Queue) showQueue() {
	fmt.Println("------------队列信息start------------")
	fmt.Printf("Front=%d Tail=%d \n", q.Front, q.Rear)
	for i := 0; i < len(q.Array); i++ {
		fmt.Printf("|  %d  |", i)
	}
	fmt.Println()
	for i := 0; i < len(q.Array); i++ {
		fmt.Printf("|  %d  |", q.Array[i])
	}
	fmt.Println()
	fmt.Println("------------队列信息end------------")
}
